﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Web;
using System.Collections;
using System.Text;
using web_uchet.Security;
namespace web_uchet.Reports.OLAP
{
    public class OLAPViewer
    {
        private ПоказателиProvider _ПоказателиProvider;
        private ProgramContext _SecurityContext;
        private OLAPSettings _Settings;
        private Dimension _DimRow;
        private Dimension _DimCol;
        private string _ViewTable = string.Empty;
        private string _HTMLTableClass = string.Empty;
        private Index _IndexViewer;

        public string FormattedData { get { return this._ViewTable; } }
        public OLAPViewer(OLAPSettings Settings, ProgramContext SecurityContext, string HTMLTableClass)
        {
            this._SecurityContext = SecurityContext;
            this._Settings = Settings;
            this._ПоказателиProvider = new ПоказателиProvider(this._Settings.Фильтр, this._SecurityContext);
            this._HTMLTableClass = HTMLTableClass;
            #region "Set Dim Types"
            this._DimCol = DimFactory.CreateDim(this._Settings.Измерение1,this._Settings.Измерение2, Settings);
            this._DimRow = DimFactory.CreateDim(this._Settings.Измерение2,this._Settings.Измерение1, Settings);            
            #endregion   
            //Do transformation before view processing
            IQueryable Data=this._ПоказателиProvider.Заказы.ToList().AsQueryable();
            Dimension CurDimCol = this._DimCol;
            Dimension CurDimRow = this._DimRow;

            this._IndexViewer = new Index(Settings.Фильтр);
            this._ViewTable=
            this.Process(this._DimCol, this._DimRow, Data);            
        }    

        public string Process(Dimension CurDimCol, Dimension CurDimRow, IQueryable Data)
        {
            #region "Something"
            StringBuilder _ResultBuilder = new StringBuilder();
            //For Interface perposes
            IQueryable DataUnModified = Data;
            Data = //CurDimCol.Where(Data);
                CurDimCol.Where(CurDimCol.TransForDim(Data));
            //If types equals, second transform and where not neaded
            if (CurDimCol.GetType()!= CurDimRow.GetType())
            Data = //CurDimRow.Where(Data); 
                CurDimRow.Where(CurDimRow.TransForDim(Data));
            //Form GroupingStr predicate
            string GroupingStr =
            string.Format("new({0} as DimCol,{1} as DimRow)",
            CurDimCol.GroupByFields[this._ПоказателиProvider.Заказы.ElementType],
            CurDimRow.GroupByFields[this._ПоказателиProvider.Заказы.ElementType]);
            IQueryable GroupedCells = Data.GroupBy(GroupingStr, "it", new object[] { });
            //Making result sets for viewing
                Dictionary<string, int> DimColGrad = CurDimCol.GetDimGraduation
                    (Data.Select(CurDimCol.GroupByFields[this._ПоказателиProvider.Заказы.ElementType]));
                Dictionary<string, int> DimRowGrad = CurDimRow.GetDimGraduation
                    (Data.Select(CurDimRow.GroupByFields[this._ПоказателиProvider.Заказы.ElementType]));
                //+1 for subtotals
                string[,] ViewAr = new string[DimRowGrad.Count,DimColGrad.Count];

                foreach (object CellData in GroupedCells)
                {
                    object Key = CellData.GetType().GetProperty("Key").GetValue(CellData, null);
                    if (CurDimCol.HasSubDim || CurDimRow.HasSubDim)
                    {
                        ViewAr[
                        DimRowGrad[CurDimRow.GetDataFromGroupingKey(Key.GetType().GetProperty("DimRow").GetValue(Key, null))],
                        DimColGrad[CurDimCol.GetDataFromGroupingKey(Key.GetType().GetProperty("DimCol").GetValue(Key, null))]]
                        = 
                            Process(CurDimCol.HasSubDim ? CurDimCol.SubDimension : CurDimCol,
                                    CurDimRow.HasSubDim ? CurDimRow.SubDimension : CurDimRow,
                                    (CellData as IEnumerable).AsQueryable());
                    }
                    else                    
                    ViewAr[
                    DimRowGrad[CurDimRow.GetDataFromGroupingKey(Key.GetType().GetProperty("DimRow").GetValue(Key, null))],
                    DimColGrad[CurDimCol.GetDataFromGroupingKey(Key.GetType().GetProperty("DimCol").GetValue(Key, null))]]
                    =
                    this._IndexViewer.DoEval(CellData as IEnumerable, true, this._Settings.ПоказателиSettings);                    
                }
                #endregion
                #region "SubTotals"
                //Sub totals
                //Row Sub Total
                foreach(object o in Data.GroupBy(
                    CurDimRow.GroupByFields[this._ПоказателиProvider.Заказы.ElementType], "it", new object[] { }))
                {
                    object Key = o.GetType().GetProperty("Key").GetValue(o, null);
                    ViewAr[DimRowGrad[CurDimRow.GetDataFromGroupingKey(Key)]
                        ,DimColGrad.Count-1]
                    = this._IndexViewer.DoEval(o as IEnumerable,
                    true, this._Settings.ПоказателиSettings);
                }
                //Col Sub Total
                foreach (object o in Data.GroupBy(
                    CurDimCol.GroupByFields[this._ПоказателиProvider.Заказы.ElementType], "it", new object[] { }))
                {
                    object Key = o.GetType().GetProperty("Key").GetValue(o, null);
                    ViewAr[DimRowGrad.Count - 1,DimColGrad[CurDimCol.GetDataFromGroupingKey(Key)]]
                    = this._IndexViewer.DoEval(o as IEnumerable,
                    true, this._Settings.ПоказателиSettings);
                }   
                //Total
                ViewAr[DimRowGrad.Count - 1, DimColGrad.Count - 1]
                    = this._IndexViewer.DoEval(DataUnModified as IEnumerable,
                    true, this._Settings.ПоказателиSettings);
                //
                #endregion
                
                #region "Rendering"
                _ResultBuilder.AppendFormat("<table class=\"{0}\"><tr><th class=\"olap-col\"></th>", this._HTMLTableClass);
                for (int i = 0; i < DimColGrad.Count-1; i++)
                    _ResultBuilder.AppendFormat("<th class=\"olap-col\">{0}</th>", DimColGrad.Keys.ElementAt(i));
                
                #region "Add SubTotal Col"
                _ResultBuilder.AppendFormat("<th class=\"olap-total\">{0}</th>", DimColGrad.Keys.ElementAt(DimColGrad.Count - 1));
                _ResultBuilder.Append("</tr>");
                #endregion "Add SubTotal Col"

                for (int i = 0; i < DimRowGrad.Count-1; i++)
                {
                    _ResultBuilder.AppendFormat("<tr><th class=\"olap-col\">{0}</th>", DimRowGrad.Keys.ElementAt(i));
                    for (int j = 0; j < DimColGrad.Count-1; j++)
                        _ResultBuilder.AppendFormat("<td class=\"olap-data\">{0}</td>", ViewAr[i, j]);

                    _ResultBuilder.AppendFormat("<td class=\"olap-total\">{0}</td>", ViewAr[i, DimColGrad.Count - 1]);
                    _ResultBuilder.Append("</tr>");
                }

                #region "Add SubTotal Row"
                _ResultBuilder.AppendFormat("<tr><th class=\"olap-total\">{0}</th>", DimRowGrad.Keys.ElementAt(DimRowGrad.Count - 1));
                for (int j = 0; j < DimColGrad.Count; j++)
                    _ResultBuilder.AppendFormat("<td class=\"olap-total\">{0}</td>", ViewAr[DimRowGrad.Count - 1, j]);
                _ResultBuilder.Append("</tr>");
                #endregion "Add SubTotal Row"
                
                _ResultBuilder.Append("</table>");
                //_ResultBuilder.Append("<input type=\"hidden\" value=\""+DateTime.Now.ToShortDateString()+"\"");
                #endregion
                return _ResultBuilder.ToString();
        }

        //public void Process(Dimension CurDimCol, Dimension CurDimRow, IQueryable Data)
        //{
        //    //For Interface perposes
        //    Data = CurDimCol.Where(CurDimCol.TransForDim(Data));
        //    Data = CurDimRow.Where(CurDimRow.TransForDim(Data));
        //    //Form GroupingStr predicate
        //    string GroupingStr =
        //    string.Format("new({0} as DimCol,{1} as DimRow)",
        //    CurDimCol.GroupByFields[this._ПоказателиProvider.Заказы.ElementType],
        //    CurDimRow.GroupByFields[this._ПоказателиProvider.Заказы.ElementType]);
        //    IQueryable GroupedCells = Data.GroupBy(GroupingStr, "it", new object[] { });
        //    //Making result sets for viewing
        //    if (CurDimCol.HasSubDim || CurDimRow.HasSubDim)
        //    {
        //        foreach (object Group in GroupedCells)
        //            Process(CurDimCol.HasSubDim ? CurDimCol.SubDimension : CurDimCol,
        //                    CurDimRow.HasSubDim ? CurDimRow.SubDimension : CurDimRow,
        //                    (Group as IEnumerable).AsQueryable());
        //    }
        //    //viewing
        //    else
        //    {
        //        Dictionary<string, int> DimColGrad = CurDimCol.GetDimGraduation
        //            (Data.Select(CurDimCol.GroupByFields[this._ПоказателиProvider.Заказы.ElementType]));
        //        Dictionary<string, int> DimRowGrad = CurDimRow.GetDimGraduation
        //            (Data.Select(CurDimRow.GroupByFields[this._ПоказателиProvider.Заказы.ElementType]));
        //        //+1 for subtotals
        //        string[,] ViewAr = new string[DimRowGrad.Count, DimColGrad.Count];

        //        foreach (object CellData in GroupedCells)
        //        {
        //            object Key = CellData.GetType().GetProperty("Key").GetValue(CellData, null);
        //            ViewAr[
        //            DimRowGrad[CurDimRow.GetDataFromGroupingKey(Key.GetType().GetProperty("DimRow").GetValue(Key, null))],
        //            DimColGrad[CurDimCol.GetDataFromGroupingKey(Key.GetType().GetProperty("DimCol").GetValue(Key, null))]]
        //            =
        //            Index.DoEval(CellData as IEnumerable, true, this._Settings.ПоказателиSettings);
        //        }
        //        //Sub totals
        //        //Row Sub Total
        //        foreach (object o in Data.GroupBy(
        //            CurDimRow.GroupByFields[this._ПоказателиProvider.Заказы.ElementType], "it", new object[] { }))
        //        {
        //            object Key = o.GetType().GetProperty("Key").GetValue(o, null);
        //            ViewAr[DimRowGrad[CurDimRow.GetDataFromGroupingKey(Key)]
        //                , DimColGrad.Count - 1]
        //            = Index.DoEval(o as IEnumerable,
        //            true, this._Settings.ПоказателиSettings);
        //        }
        //        //Col Sub Total
        //        foreach (object o in Data.GroupBy(
        //            CurDimCol.GroupByFields[this._ПоказателиProvider.Заказы.ElementType], "it", new object[] { }))
        //        {
        //            object Key = o.GetType().GetProperty("Key").GetValue(o, null);
        //            ViewAr[DimRowGrad.Count - 1, DimColGrad[CurDimCol.GetDataFromGroupingKey(Key)]]
        //            = Index.DoEval(o as IEnumerable,
        //            true, this._Settings.ПоказателиSettings);
        //        }
        //        //Total
        //        ViewAr[DimRowGrad.Count - 1, DimColGrad.Count - 1]
        //            = Index.DoEval(Data as IEnumerable,
        //            true, this._Settings.ПоказателиSettings);
        //        //

        //        this._ResultBuilder.AppendFormat("<table class=\"{0}\"><tr><th></th>", this._HTMLTableClass);
        //        foreach (string s in DimColGrad.Keys)
        //            this._ResultBuilder.AppendFormat("<th>{0}</th>", s);
        //        this._ResultBuilder.Append("</tr>");

        //        for (int i = 0; i < DimRowGrad.Count; i++)
        //        {
        //            this._ResultBuilder.AppendFormat("<tr><th>{0}</th>", DimRowGrad.Keys.ElementAt(i));
        //            for (int j = 0; j < DimColGrad.Count; j++)
        //                this._ResultBuilder.AppendFormat("<td>{0}</td>", ViewAr[i, j]);
        //            this._ResultBuilder.Append("</tr>");
        //        }


        //        this._ResultBuilder.Append("</table>");
        //        #region "old"
        //        //this._ResultBuilder.Append("<table><tr><th></th>");
        //        //StringBuilder RowBuilder = new StringBuilder();
        //        //foreach (object CellData in GroupedCells)
        //        //{
        //        //    object Key = CellData.GetType().GetProperty("Key").GetValue(CellData, null);
        //        //    this._ResultBuilder.AppendFormat("<th>{0}</th>",
        //        //        CurDimCol.GetDataFromGroupingKey(Key.GetType().GetProperty("DimCol").GetValue(Key, null)));

        //        //    RowBuilder.AppendFormat("<tr><th>{0}</th>",
        //        //        CurDimRow.GetDataFromGroupingKey(Key.GetType().GetProperty("DimRow").GetValue(Key, null)));

        //        //    RowBuilder.AppendFormat("<td>{0}</td>",
        //        //    Index.DoEval(CellData as IEnumerable, true, this._Settings.ПоказателиSettings));

        //        //    RowBuilder.Append("</tr>");
        //        //}
        //        //this._ResultBuilder.AppendFormat("</tr>{0}</table>", RowBuilder.ToString());
        //        #endregion
        //    }
        //}
    }
}
